home *** CD-ROM | disk | FTP | other *** search
/ The Complete Utilities To…ka 501 Killer Utilities! / 501 Killer Utilities! (Macworld July 1995).cdr / Programming / OutOfPhase1.1 Source / OutOfPhase Folder / CalculatorWindow.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-01-05  |  28.5 KB  |  958 lines  |  [TEXT/KAHL]

  1. /* CalculatorWindow.c */
  2. /*****************************************************************************/
  3. /*                                                                           */
  4. /*    Out Of Phase:  Digital Music Synthesis on General Purpose Computers    */
  5. /*    Copyright (C) 1994  Thomas R. Lawrence                                 */
  6. /*                                                                           */
  7. /*    This program is free software; you can redistribute it and/or modify   */
  8. /*    it under the terms of the GNU General Public License as published by   */
  9. /*    the Free Software Foundation; either version 2 of the License, or      */
  10. /*    (at your option) any later version.                                    */
  11. /*                                                                           */
  12. /*    This program is distributed in the hope that it will be useful,        */
  13. /*    but WITHOUT ANY WARRANTY; without even the implied warranty of         */
  14. /*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          */
  15. /*    GNU General Public License for more details.                           */
  16. /*                                                                           */
  17. /*    You should have received a copy of the GNU General Public License      */
  18. /*    along with this program; if not, write to the Free Software            */
  19. /*    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.              */
  20. /*                                                                           */
  21. /*    Thomas R. Lawrence can be reached at tomlaw@world.std.com.             */
  22. /*                                                                           */
  23. /*****************************************************************************/
  24.  
  25. #include "MiscInfo.h"
  26. #include "Audit.h"
  27. #include "Debug.h"
  28. #include "Definitions.h"
  29.  
  30. #include "CalculatorWindow.h"
  31. #include "Screen.h"
  32. #include "TextEdit.h"
  33. #include "Memory.h"
  34. #include "MainWindowStuff.h"
  35. #include "GrowIcon.h"
  36. #include "Main.h"
  37. #include "SimpleButton.h"
  38. #include "Alert.h"
  39. #include "CodeCenter.h"
  40. #include "PcodeStack.h"
  41. #include "PcodeSystem.h"
  42. #include "DataMunging.h"
  43. #include "Numbers.h"
  44. #include "FixedPoint.h"
  45. #include "WindowDispatcher.h"
  46. #include "GlobalWindowMenuList.h"
  47. #include "FunctionCode.h"
  48. #include "CompilerRoot.h"
  49. #include "PcodeDisassembly.h"
  50. #include "DisassemblyWindow.h"
  51. #include "FindDialog.h"
  52.  
  53.  
  54. #define WINDOWLEFT (30)
  55. #define WINDOWTOP (30)
  56. #define WINDOWWIDTH (450)
  57. #define WINDOWHEIGHT (200)
  58.  
  59. #define BUTTONLEFT (10)
  60. #define BUTTONTOP (2)
  61. #define BUTTONWIDTH (120)
  62. #define BUTTONHEIGHT (19)
  63.  
  64. struct CalcWindowRec
  65.     {
  66.         MainWindowRec*            MainWindow;
  67.         CodeCenterRec*            CodeCenter;
  68.  
  69.         WinType*                        ScreenID;
  70.         GenericWindowRec*        MyGenericWindow; /* how the window event dispatcher knows us */
  71.         MenuItemType*                MyMenuItem;
  72.         TextEditRec*                Editor;
  73.         long                                LastLine;
  74.         SimpleButtonRec*        EvalButton;
  75.     };
  76.  
  77.  
  78. /* create a new calculator window.  the caller is responsible for registering the */
  79. /* new calculator with the main window. */
  80. CalcWindowRec*            NewCalculatorWindow(struct MainWindowRec* MainWindow,
  81.                                             struct CodeCenterRec* CodeCenter)
  82.     {
  83.         CalcWindowRec*        Window;
  84.  
  85.         CheckPtrExistence(MainWindow);
  86.         CheckPtrExistence(CodeCenter);
  87.         Window = (CalcWindowRec*)AllocPtrCanFail(sizeof(CalcWindowRec),"CalcWindowRec");
  88.         if (Window == NIL)
  89.             {
  90.              FailurePoint1:
  91.                 return NIL;
  92.             }
  93.         Window->MainWindow = MainWindow;
  94.         Window->CodeCenter = CodeCenter;
  95.         Window->ScreenID = MakeNewWindow(eDocumentWindow,eWindowClosable,
  96.             eWindowZoomable,eWindowResizable,WINDOWLEFT,WINDOWTOP,WINDOWWIDTH,WINDOWHEIGHT,
  97.             (void (*)(void*))&CalculatorWindowUpdator,Window);
  98.         if (Window->ScreenID == 0)
  99.             {
  100.              FailurePoint2:
  101.                 ReleasePtr((char*)Window);
  102.                 goto FailurePoint1;
  103.             }
  104.         SetWindowName(Window->ScreenID,"Calculator");
  105.         Window->Editor = NewTextEdit(Window->ScreenID,
  106.             (TEScrollType)(eTEVScrollBar | eTEHScrollBar),GetMonospacedFont(),9,
  107.             -1,(2 * BUTTONTOP) + BUTTONHEIGHT,WINDOWWIDTH + 2,
  108.             WINDOWHEIGHT + 1 - ((2 * BUTTONTOP) + BUTTONHEIGHT));
  109.         if (Window->Editor == NIL)
  110.             {
  111.              FailurePoint3:
  112.                 KillWindow(Window->ScreenID);
  113.                 goto FailurePoint2;
  114.             }
  115.         Window->LastLine = 0;
  116.         Window->EvalButton = NewSimpleButton(Window->ScreenID,"Evaluate",
  117.             BUTTONLEFT,BUTTONTOP,BUTTONWIDTH,BUTTONHEIGHT);
  118.         if (Window->EvalButton == NIL)
  119.             {
  120.              FailurePoint4:
  121.                 DisposeTextEdit(Window->Editor);
  122.                 goto FailurePoint3;
  123.             }
  124.         Window->MyGenericWindow = CheckInNewWindow(Window->ScreenID,Window,
  125.             (void (*)(void*,MyBoolean,OrdType,OrdType,ModifierFlags))&CalculatorWindowDoIdle,
  126.             (void (*)(void*))&CalculatorWindowBecomeActive,
  127.             (void (*)(void*))&CalculatorWindowBecomeInactive,
  128.             (void (*)(void*))&CalculatorWindowJustResized,
  129.             (void (*)(OrdType,OrdType,ModifierFlags,void*))&CalculatorWindowDoMouseDown,
  130.             (void (*)(unsigned char,ModifierFlags,void*))&CalculatorWindowDoKeyDown,
  131.             (void (*)(void*))&CalculatorWindowClose,
  132.             (void (*)(void*))&CalculatorWindowMenuSetup,
  133.             (void (*)(void*,MenuItemType*))&CalculatorWindowDoMenuCommand);
  134.         if (Window->MyGenericWindow == NIL)
  135.             {
  136.              FailurePoint5:
  137.                 DisposeSimpleButton(Window->EvalButton);
  138.                 goto FailurePoint4;
  139.             }
  140.         Window->MyMenuItem = MakeNewMenuItem(mmWindowMenu,"Calculator",0);
  141.         if (Window->MyMenuItem == NIL)
  142.             {
  143.              FailurePoint6:
  144.                 CheckOutDyingWindow(Window->MyGenericWindow);
  145.                 goto FailurePoint5;
  146.             }
  147.         if (!RegisterWindowMenuItem(Window->MyMenuItem,(void (*)(void*))&ActivateThisWindow,
  148.             Window->ScreenID))
  149.             {
  150.              FailurePoint7:
  151.                 KillMenuItem(Window->MyMenuItem);
  152.                 goto FailurePoint6;
  153.             }
  154.         SetTextEditAutoIndent(Window->Editor,True);
  155.         SetTextEditTabSize(Window->Editor,MainWindowGetTabSize(MainWindow));
  156.         return Window;
  157.     }
  158.  
  159.  
  160. /* dispose of a calculator window.  the calculator notifies the main window that */
  161. /* owns it. */
  162. void                                DisposeCalculatorWindow(CalcWindowRec* Window)
  163.     {
  164.         CheckPtrExistence(Window);
  165.         DeregisterWindowMenuItem(Window->MyMenuItem);
  166.         KillMenuItem(Window->MyMenuItem);
  167.         CheckOutDyingWindow(Window->MyGenericWindow);
  168.         DisposeSimpleButton(Window->EvalButton);
  169.         DisposeTextEdit(Window->Editor);
  170.         KillWindow(Window->ScreenID);
  171.         ReleasePtr((char*)Window);
  172.     }
  173.  
  174.  
  175. void                                CalculatorWindowDoIdle(CalcWindowRec* Window,
  176.                                             MyBoolean CheckCursorFlag, OrdType XLoc, OrdType YLoc,
  177.                                             ModifierFlags Modifiers)
  178.     {
  179.         CheckPtrExistence(Window);
  180.         TextEditUpdateCursor(Window->Editor);
  181.         if (CheckCursorFlag)
  182.             {
  183.                 if (TextEditIBeamTest(Window->Editor,XLoc,YLoc))
  184.                     {
  185.                         SetIBeamCursor();
  186.                     }
  187.                  else
  188.                     {
  189.                         SetArrowCursor();
  190.                     }
  191.             }
  192.     }
  193.  
  194.  
  195. void                                CalculatorWindowBecomeActive(CalcWindowRec* Window)
  196.     {
  197.         OrdType                        XSize;
  198.         OrdType                        YSize;
  199.  
  200.         CheckPtrExistence(Window);
  201.         EnableTextEditSelection(Window->Editor);
  202.         XSize = GetWindowWidth(Window->ScreenID);
  203.         YSize = GetWindowHeight(Window->ScreenID);
  204.         SetClipRect(Window->ScreenID,XSize - 15,YSize - 15,XSize,YSize);
  205.         DrawBitmap(Window->ScreenID,XSize-15,YSize-15,GetGrowIcon(True/*enablegrowicon*/));
  206.     }
  207.  
  208.  
  209. void                                CalculatorWindowBecomeInactive(CalcWindowRec* Window)
  210.     {
  211.         OrdType                        XSize;
  212.         OrdType                        YSize;
  213.  
  214.         CheckPtrExistence(Window);
  215.         DisableTextEditSelection(Window->Editor);
  216.         XSize = GetWindowWidth(Window->ScreenID);
  217.         YSize = GetWindowHeight(Window->ScreenID);
  218.         SetClipRect(Window->ScreenID,XSize - 15,YSize - 15,XSize,YSize);
  219.         DrawBitmap(Window->ScreenID,XSize-15,YSize-15,GetGrowIcon(False/*disablegrowicon*/));
  220.     }
  221.  
  222.  
  223. void                                CalculatorWindowJustResized(CalcWindowRec* Window)
  224.     {
  225.         OrdType                        XSize;
  226.         OrdType                        YSize;
  227.  
  228.         CheckPtrExistence(Window);
  229.         XSize = GetWindowWidth(Window->ScreenID);
  230.         YSize = GetWindowHeight(Window->ScreenID);
  231.         SetClipRect(Window->ScreenID,0,0,XSize,YSize);
  232.         DrawBoxErase(Window->ScreenID,0,0,XSize,YSize);
  233.         SetTextEditPosition(Window->Editor,-1,(2 * BUTTONTOP) + BUTTONHEIGHT,
  234.             XSize + 2,YSize + 1 - ((2 * BUTTONTOP) + BUTTONHEIGHT));
  235.     }
  236.  
  237.  
  238. void                                CalculatorWindowDoMouseDown(OrdType XLoc, OrdType YLoc,
  239.                                             ModifierFlags Modifiers, CalcWindowRec* Window)
  240.     {
  241.         CheckPtrExistence(Window);
  242.         if ((XLoc >= GetWindowWidth(Window->ScreenID) - 15)
  243.             && (XLoc < GetWindowWidth(Window->ScreenID))
  244.             && (YLoc >= GetWindowHeight(Window->ScreenID) - 15)
  245.             && (YLoc < GetWindowHeight(Window->ScreenID)))
  246.             {
  247.                 UserGrowWindow(Window->ScreenID,XLoc,YLoc);
  248.                 CalculatorWindowJustResized(Window);
  249.             }
  250.         else if (TextEditHitTest(Window->Editor,XLoc,YLoc))
  251.             {
  252.                 TextEditDoMouseDown(Window->Editor,XLoc,YLoc,Modifiers);
  253.             }
  254.         else if (SimpleButtonHitTest(Window->EvalButton,XLoc,YLoc))
  255.             {
  256.                 if (SimpleButtonMouseDown(Window->EvalButton,XLoc,YLoc,NIL,NIL))
  257.                     {
  258.                         CalculatorWindowDoCalculation(Window);
  259.                     }
  260.             }
  261.     }
  262.  
  263.  
  264. void                                CalculatorWindowDoKeyDown(unsigned char KeyCode,
  265.                                             ModifierFlags Modifiers, CalcWindowRec* Window)
  266.     {
  267.         CheckPtrExistence(Window);
  268.         TextEditDoKeyPressed(Window->Editor,KeyCode,Modifiers);
  269.     }
  270.  
  271.  
  272. void                                CalculatorWindowClose(CalcWindowRec* Window)
  273.     {
  274.         CheckPtrExistence(Window);
  275.         /* notification of closing is here and not in dispose because FunctionWindow */
  276.         /* calls dispose, so it knows that we are dying, but this routine handles */
  277.         /* a user close, which FunctionWindow doesn't know about */
  278.         MainWindowCalculatorClosingNotify(Window->MainWindow,Window);
  279.         DisposeCalculatorWindow(Window);
  280.     }
  281.  
  282.  
  283. void                                CalculatorWindowUpdator(CalcWindowRec* Window)
  284.     {
  285.         OrdType            XSize;
  286.         OrdType            YSize;
  287.  
  288.         CheckPtrExistence(Window);
  289.         TextEditFullRedraw(Window->Editor);
  290.         RedrawSimpleButton(Window->EvalButton);
  291.         XSize = GetWindowWidth(Window->ScreenID);
  292.         YSize = GetWindowHeight(Window->ScreenID);
  293.         SetClipRect(Window->ScreenID,XSize - 15,YSize - 15,XSize,YSize);
  294.         DrawBitmap(Window->ScreenID,XSize-15,YSize-15,
  295.             GetGrowIcon(Window->MyGenericWindow == GetCurrentWindowID()));
  296.     }
  297.  
  298.  
  299. void                                CalculatorWindowMenuSetup(CalcWindowRec* Window)
  300.     {
  301.         CheckPtrExistence(Window);
  302.         MainWindowEnableGlobalMenus(Window->MainWindow);
  303.         EnableMenuItem(mPaste);
  304.         ChangeItemName(mPaste,"Paste Text");
  305.         if (TextEditIsThereValidSelection(Window->Editor))
  306.             {
  307.                 EnableMenuItem(mCut);
  308.                 ChangeItemName(mCut,"Cut Text");
  309.                 EnableMenuItem(mCopy);
  310.                 ChangeItemName(mCopy,"Copy Text");
  311.                 EnableMenuItem(mClear);
  312.                 ChangeItemName(mClear,"Clear Text");
  313.             }
  314.         EnableMenuItem(mShiftLeft);
  315.         EnableMenuItem(mShiftRight);
  316.         EnableMenuItem(mBalanceParens);
  317.         EnableMenuItem(mSelectAll);
  318.         ChangeItemName(mSelectAll,"Select All Text");
  319.         if (TextEditCanWeUndo(Window->Editor))
  320.             {
  321.                 EnableMenuItem(mUndo);
  322.                 ChangeItemName(mUndo,"Undo Text Change");
  323.             }
  324.         EnableMenuItem(mFind);
  325.         if (PtrSize(GlobalSearchString) != 0)
  326.             {
  327.                 EnableMenuItem(mFindAgain);
  328.                 if (TextEditIsThereValidSelection(Window->Editor))
  329.                     {
  330.                         EnableMenuItem(mReplace);
  331.                         EnableMenuItem(mReplaceAndFindAgain);
  332.                     }
  333.             }
  334.         EnableMenuItem(mShowSelection);
  335.         if (TextEditIsThereValidSelection(Window->Editor))
  336.             {
  337.                 EnableMenuItem(mEnterSelection);
  338.             }
  339.         ChangeItemName(mCloseFile,"Close Calculator");
  340.         EnableMenuItem(mCloseFile);
  341.         EnableMenuItem(mEvaluateCalc);
  342.         SetItemCheckmark(Window->MyMenuItem);
  343.         EnableMenuItem(mDisassembleFunction);
  344.         ChangeItemName(mDisassembleFunction,"Disassemble Calculator Expression");
  345.     }
  346.  
  347.  
  348. void                                CalculatorWindowDoMenuCommand(CalcWindowRec* Window,
  349.                                             MenuItemType* MenuItem)
  350.     {
  351.         CheckPtrExistence(Window);
  352.         if (MainWindowDoGlobalMenuItem(Window->MainWindow,MenuItem))
  353.             {
  354.             }
  355.         else if (MenuItem == mPaste)
  356.             {
  357.                 TextEditDoMenuPaste(Window->Editor);
  358.             }
  359.         else if (MenuItem == mCut)
  360.             {
  361.                 TextEditDoMenuCut(Window->Editor);
  362.             }
  363.         else if (MenuItem == mCopy)
  364.             {
  365.                 TextEditDoMenuCopy(Window->Editor);
  366.             }
  367.         else if (MenuItem == mClear)
  368.             {
  369.                 TextEditDoMenuClear(Window->Editor);
  370.             }
  371.         else if (MenuItem == mSelectAll)
  372.             {
  373.                 TextEditDoMenuSelectAll(Window->Editor);
  374.             }
  375.         else if (MenuItem == mUndo)
  376.             {
  377.                 TextEditDoMenuUndo(Window->Editor);
  378.             }
  379.         else if (MenuItem == mCloseFile)
  380.             {
  381.                 CalculatorWindowClose(Window);
  382.             }
  383.         else if (MenuItem == mShiftLeft)
  384.             {
  385.                 TextEditShiftSelectionLeftOneTab(Window->Editor);
  386.             }
  387.         else if (MenuItem == mShiftRight)
  388.             {
  389.                 TextEditShiftSelectionRightOneTab(Window->Editor);
  390.             }
  391.         else if (MenuItem == mBalanceParens)
  392.             {
  393.                 TextEditBalanceParens(Window->Editor);
  394.             }
  395.         else if (MenuItem == mEvaluateCalc)
  396.             {
  397.                 CalculatorWindowDoCalculation(Window);
  398.             }
  399.         else if (MenuItem == mDisassembleFunction)
  400.             {
  401.                 char*                                Blob;
  402.                 PcodeRec*                        FuncCode;
  403.                 CompileErrors                Error;
  404.                 long                                LineNumber;
  405.                 DataTypes                        ReturnType;
  406.                 char*                                DisassemblyText;
  407.  
  408.                 /* prepare the text blob to be evaluated */
  409.                 if (!TextEditIsThereValidSelection(Window->Editor))
  410.                     {
  411.                         if (Window->LastLine > GetTextEditNumLines(Window->Editor))
  412.                             {
  413.                                 Window->LastLine = GetTextEditNumLines(Window->Editor);
  414.                             }
  415.                         SetTextEditSelection(Window->Editor,Window->LastLine,0,
  416.                             GetTextEditNumLines(Window->Editor),0);
  417.                     }
  418.                 Blob = TextEditGetSelection(Window->Editor);
  419.                 if (Blob == NIL)
  420.                     {
  421.                      FailurePoint1:
  422.                         AlertHalt("There is not enough memory available to compile "
  423.                             "the expression.",NIL);
  424.                         return;
  425.                     }
  426.  
  427.                 /* perform compilation */
  428.                 EXECUTE(FuncCode = NIL;)
  429.                 Error = CompileSpecialFunction(NIL/*no arguments*/,0/*noargs*/,&LineNumber,
  430.                     &ReturnType,Blob/*text*/,&FuncCode);
  431.                 ReleasePtr(Blob);
  432.                 if (Error != eCompileNoError)
  433.                     {
  434.                         ERROR(FuncCode != NIL,PRERR(ForceAbort,"CalculatorWindowDoMenuCommand:  "
  435.                             "compile failed, but function is not NIL."));
  436.                         SetTextEditSelection(Window->Editor,
  437.                             GetTextEditSelectStartLine(Window->Editor) + LineNumber,0,
  438.                             GetTextEditSelectStartLine(Window->Editor) + LineNumber + 1,0);
  439.                         TextEditShowSelection(Window->Editor);
  440.                         AlertHalt("A compile error occurred:  _",GetCompileErrorString(Error));
  441.                         return;
  442.                     }
  443.  
  444.                 /* obtain the disassembly */
  445.                 DisassemblyText = DisassemblePcode(FuncCode,'\x0a');
  446.                 DisposePcode(FuncCode);
  447.                 if (DisassemblyText == NIL)
  448.                     {
  449.                         AlertHalt("There is not enough memory available to disassemble "
  450.                             "the expression.",NIL);
  451.                         return;
  452.                     }
  453.  
  454.                 /* show it */
  455.                 if (NewDisassemblyWindow(DisassemblyText,Window->MainWindow) == NIL)
  456.                     {
  457.                         AlertHalt("There is not enough memory available to "
  458.                             "show the disassembly window.",NIL);
  459.                     }
  460.                 ReleasePtr(DisassemblyText);
  461.             }
  462.         else if (MenuItem == mFind)
  463.             {
  464.                 switch (DoFindDialog(&GlobalSearchString,&GlobalReplaceString,
  465.                     mCut,mPaste,mCopy,mUndo,mSelectAll,mClear))
  466.                     {
  467.                         default:
  468.                             EXECUTE(PRERR(ForceAbort,
  469.                                 "CalculatorWindowDoMenuCommand:  bad value from DoFindDialog"));
  470.                             break;
  471.                         case eFindCancel:
  472.                         case eDontFind:
  473.                             break;
  474.                         case eFindFromStart:
  475.                             SetTextEditInsertionPoint(Window->Editor,0,0);
  476.                             TextEditFindAgain(Window->Editor,GlobalSearchString);
  477.                             TextEditShowSelection(Window->Editor);
  478.                             break;
  479.                         case eFindAgain:
  480.                             TextEditFindAgain(Window->Editor,GlobalSearchString);
  481.                             TextEditShowSelection(Window->Editor);
  482.                             break;
  483.                     }
  484.             }
  485.         else if (MenuItem == mFindAgain)
  486.             {
  487.                 TextEditFindAgain(Window->Editor,GlobalSearchString);
  488.                 TextEditShowSelection(Window->Editor);
  489.             }
  490.         else if (MenuItem == mReplace)
  491.             {
  492.                 if (TextEditIsThereValidSelection(Window->Editor))
  493.                     {
  494.                         TextEditInsertRawDataWithUndo(Window->Editor,GlobalReplaceString,
  495.                             SYSTEMLINEFEED);
  496.                     }
  497.             }
  498.         else if (MenuItem == mReplaceAndFindAgain)
  499.             {
  500.                 if (TextEditIsThereValidSelection(Window->Editor))
  501.                     {
  502.                         TextEditInsertRawDataWithUndo(Window->Editor,GlobalReplaceString,
  503.                             SYSTEMLINEFEED);
  504.                         TextEditFindAgain(Window->Editor,GlobalSearchString);
  505.                         TextEditShowSelection(Window->Editor);
  506.                     }
  507.             }
  508.         else if (MenuItem == mShowSelection)
  509.             {
  510.                 TextEditShowSelection(Window->Editor);
  511.             }
  512.         else if (MenuItem == mEnterSelection)
  513.             {
  514.                 char*                        NewString;
  515.  
  516.                 NewString = TextEditGetSelection(Window->Editor);
  517.                 if (NewString != NIL)
  518.                     {
  519.                         ReleasePtr(GlobalSearchString);
  520.                         GlobalSearchString = NewString;
  521.                     }
  522.             }
  523.         else
  524.             {
  525.                 EXECUTE(PRERR(AllowResume,"CalculatorWindowDoMenuCommand:  unknown menu command"));
  526.             }
  527.     }
  528.  
  529.  
  530. /* perform evaluation.  if there is a selection, then evaluate */
  531. /* the selection, otherwise evaluate from last point */
  532. void                                CalculatorWindowDoCalculation(CalcWindowRec* Window)
  533.     {
  534.         char*                                Blob;
  535.         PcodeRec*                        FuncCode;
  536.         CompileErrors                Error;
  537.         long                                LineNumber;
  538.         DataTypes                        ReturnType;
  539.         ParamStackRec*            ParamList;
  540.         EvalErrors                    OtherError;
  541.         OpcodeRec*                    ErrorOpcode;
  542.         long                                OffendingInstruction;
  543.         char*                                Number;
  544.         char*                                Statement;
  545.         MyBoolean                        MemoryErrorOccurred;
  546.  
  547.         CheckPtrExistence(Window);
  548.  
  549.         /* bring the world up to date */
  550.         if (!MainWindowMakeUpToDateFunctions(Window->MainWindow))
  551.             {
  552.                 return;
  553.             }
  554.  
  555.         /* prepare the text blob to be evaluated */
  556.         if (!TextEditIsThereValidSelection(Window->Editor))
  557.             {
  558.                 if (Window->LastLine > GetTextEditNumLines(Window->Editor))
  559.                     {
  560.                         Window->LastLine = GetTextEditNumLines(Window->Editor);
  561.                     }
  562.                 SetTextEditSelection(Window->Editor,Window->LastLine,0,
  563.                     GetTextEditNumLines(Window->Editor),0);
  564.             }
  565.         Blob = TextEditGetSelection(Window->Editor);
  566.         if (Blob == NIL)
  567.             {
  568.              FailurePoint1:
  569.                 AlertHalt("There is not enough memory available to compile the expression.",NIL);
  570.                 return;
  571.             }
  572.  
  573.         /* perform compilation */
  574.         EXECUTE(FuncCode = NIL;)
  575.         Error = CompileSpecialFunction(NIL/*no arguments*/,0/*noargs*/,&LineNumber,
  576.             &ReturnType,Blob/*text*/,&FuncCode);
  577.         ReleasePtr(Blob);
  578.         if (Error != eCompileNoError)
  579.             {
  580.                 ERROR(FuncCode != NIL,PRERR(ForceAbort,
  581.                     "CalculatorWindowDoCalculation:  compile failed, but function is not NIL."));
  582.                 SetTextEditSelection(Window->Editor,GetTextEditSelectStartLine(Window->Editor)
  583.                     + LineNumber,0,GetTextEditSelectStartLine(Window->Editor) + LineNumber + 1,0);
  584.                 TextEditShowSelection(Window->Editor);
  585.                 AlertHalt("A compile error occurred:  _",GetCompileErrorString(Error));
  586.                 return;
  587.             }
  588.  
  589.         /* try to evaluate the code */
  590.         ParamList = NewParamStack();
  591.         if (ParamList == NIL)
  592.             {
  593.              SecondFailurePoint1:
  594.                 DisposePcode(FuncCode);
  595.                 AlertHalt("There is not enough memory available to evaluate the expression.",NIL);
  596.                 return;
  597.             }
  598.         /* add a space for the return value */
  599.         if (!AddIntegerToStack(ParamList,0))
  600.             {
  601.              SecondFailurePoint2:
  602.                 goto SecondFailurePoint1;
  603.             }
  604.         /* executing the actual code */
  605.         OtherError = EvaluatePcode(ParamList,FuncCode,
  606.             Window->CodeCenter,&ErrorOpcode,&OffendingInstruction,Window->MainWindow,
  607.             (SampleErrors (*)(void*,char*,largefixedsigned**))&MainWindowGetSampleLeftCopy,
  608.             (SampleErrors (*)(void*,char*,largefixedsigned**))&MainWindowGetSampleRightCopy,
  609.             (SampleErrors (*)(void*,char*,largefixedsigned**))&MainWindowGetSampleMonoCopy,
  610.             (SampleErrors (*)(void*,char*,long*))&MainWindowGetWaveTableFrameCount,
  611.             (SampleErrors (*)(void*,char*,long*))&MainWindowGetWaveTableTableCount,
  612.             (SampleErrors (*)(void*,char*,largefixedsigned**))&MainWindowGetWaveTableArray,
  613.             Window->MainWindow,
  614.             (struct InteractionWindowRec* (*)(void*))&MainWindowGetInteractionWindow);
  615.         if (OtherError != eEvalNoError)
  616.             {
  617.                 char*                    FuncNameString;
  618.                 MyBoolean            SuccessFlag;
  619.  
  620.                 /* present error message */
  621.                 SuccessFlag = False;
  622.                 if (GetOpcodeFromPcode(FuncCode) == ErrorOpcode)
  623.                     {
  624.                         /* our function, not a library function */
  625.                         FuncNameString = StringToBlockCopy("<anonymous>");
  626.                     }
  627.                  else
  628.                     {
  629.                         /* it is a library function, so look it up */
  630.                         FuncNameString = CopyPtr(GetFunctionName(
  631.                             GetFunctionFromOpcode(Window->CodeCenter,ErrorOpcode)));
  632.                     }
  633.                 if (FuncNameString != NIL)
  634.                     {
  635.                         char*                    Key;
  636.  
  637.                         Key = StringToBlockCopy("_");
  638.                         if (Key != NIL)
  639.                             {
  640.                                 char*                    BaseMessage;
  641.  
  642.                                 BaseMessage = StringFromRaw("Error in function _, instruction _:  _");
  643.                                 if (BaseMessage != NIL)
  644.                                     {
  645.                                         char*                    FixedMessage1;
  646.  
  647.                                         FixedMessage1 = ReplaceBlockCopy(BaseMessage,Key,FuncNameString);
  648.                                         if (FixedMessage1 != NIL)
  649.                                             {
  650.                                                 char*                    NumberStr;
  651.  
  652.                                                 NumberStr = IntegerToString(OffendingInstruction);
  653.                                                 if (NumberStr != NIL)
  654.                                                     {
  655.                                                         char*                    FixedMessage2;
  656.  
  657.                                                         FixedMessage2 = ReplaceBlockCopy(FixedMessage1,Key,NumberStr);
  658.                                                         if (FixedMessage2 != NIL)
  659.                                                             {
  660.                                                                 AlertHalt(FixedMessage2,GetPcodeErrorMessage(OtherError));
  661.                                                                 SuccessFlag = True;
  662.                                                                 ReleasePtr(FixedMessage2);
  663.                                                             }
  664.                                                         ReleasePtr(NumberStr);
  665.                                                     }
  666.                                                 ReleasePtr(FixedMessage1);
  667.                                             }
  668.                                         ReleasePtr(BaseMessage);
  669.                                     }
  670.                                 ReleasePtr(Key);
  671.                             }
  672.                         ReleasePtr(FuncNameString);
  673.                     }
  674.                 if (!SuccessFlag)
  675.                     {
  676.                         AlertHalt("There is not enough memory available to show "
  677.                             "the compile error message.",NIL);
  678.                     }
  679.                 DisposeParamStack(ParamList);
  680.                 DisposePcode(FuncCode);
  681.                 return;
  682.             }
  683.  
  684.         /* add new data to window */
  685.         MemoryErrorOccurred = False;
  686.         TextEditAppendLineInteraction(Window->Editor,NIL);
  687.         switch (ReturnType)
  688.             {
  689.                 default:
  690.                     EXECUTE(PRERR(ForceAbort,"CalculatorWindowDoCalculation:  unknown type"));
  691.                     break;
  692.                 case eBoolean:
  693.                     /* prepare value */
  694.                     if (GetStackInteger(ParamList,0) != 0)
  695.                         {
  696.                             Number = StringToBlockCopy("true");
  697.                         }
  698.                      else
  699.                         {
  700.                             Number = StringToBlockCopy("false");
  701.                         }
  702.                     Statement = StringToBlockCopy("returns boolean:  _");
  703.                     /* put value in editor */
  704.                  ScalarMakePoint:
  705.                     if (Number != NIL)
  706.                         {
  707.                             if (Statement != NIL)
  708.                                 {
  709.                                     char*                Key;
  710.  
  711.                                     Key = StringToBlockCopy("_");
  712.                                     if (Key != NIL)
  713.                                         {
  714.                                             char*                Fixer;
  715.  
  716.                                             Fixer = ReplaceBlockCopy(Statement,Key,Number);
  717.                                             if (Fixer != NIL)
  718.                                                 {
  719.                                                     TextEditAppendLineInteraction(Window->Editor,Fixer);
  720.                                                     ReleasePtr(Fixer);
  721.                                                 }
  722.                                              else
  723.                                                 {
  724.                                                     MemoryErrorOccurred = True;
  725.                                                 }
  726.                                             ReleasePtr(Key);
  727.                                         }
  728.                                      else
  729.                                         {
  730.                                             MemoryErrorOccurred = True;
  731.                                         }
  732.                                 }
  733.                              else
  734.                                 {
  735.                                     MemoryErrorOccurred = True;
  736.                                 }
  737.                         }
  738.                      else
  739.                         {
  740.                             MemoryErrorOccurred = True;
  741.                         }
  742.                     /* dispose values */
  743.                     if (Number != NIL)
  744.                         {
  745.                             ReleasePtr(Number);
  746.                         }
  747.                     if (Statement != NIL)
  748.                         {
  749.                             ReleasePtr(Statement);
  750.                         }
  751.                     break;
  752.                 case eInteger:
  753.                     Number = IntegerToString(GetStackInteger(ParamList,0));
  754.                     Statement = StringToBlockCopy("returns integer:  _");
  755.                     goto ScalarMakePoint;
  756.                 case eFixed:
  757.                     Number = LongDoubleToString(
  758.                         largefixed2double(GetStackInteger(ParamList,0)),11,1e-9,1e6);
  759.                     Statement = StringToBlockCopy("returns fixed:  _");
  760.                     goto ScalarMakePoint;
  761.                 case eFloat:
  762.                     Number = LongDoubleToString(GetStackFloat(ParamList,0),7,1e-4,1e6);
  763.                     Statement = StringToBlockCopy("returns float:  _");
  764.                     goto ScalarMakePoint;
  765.                 case eDouble:
  766.                     Number = LongDoubleToString(GetStackLongDouble(ParamList,0),15,1e-4,1e6);
  767.                     Statement = StringToBlockCopy("returns double:  _");
  768.                     goto ScalarMakePoint;
  769.                 case eArrayOfBoolean:
  770.                     Statement = StringToBlockCopy("returns array of boolean:");
  771.                     goto ArrayMakePoint;
  772.                 case eArrayOfInteger:
  773.                     Statement = StringToBlockCopy("returns array of integer:");
  774.                     goto ArrayMakePoint;
  775.                 case eArrayOfFixed:
  776.                     Statement = StringToBlockCopy("returns array of fixed:");
  777.                     goto ArrayMakePoint;
  778.                 case eArrayOfFloat:
  779.                     Statement = StringToBlockCopy("returns array of float:");
  780.                     goto ArrayMakePoint;
  781.                 case eArrayOfDouble:
  782.                     /* construct statement */
  783.                     Statement = StringToBlockCopy("returns array of double:");
  784.                  ArrayMakePoint:
  785.                     if (Statement != NIL)
  786.                         {
  787.                             void*                    Array;
  788.  
  789.                             TextEditAppendLineInteraction(Window->Editor,Statement);
  790.                             ReleasePtr(Statement);
  791.                             Array = GetStackArray(ParamList,0);
  792.                             if (Array == NIL)
  793.                                 {
  794.                                     char*                    Thang;
  795.  
  796.                                     Thang = StringToBlockCopy("NIL");
  797.                                     if (Thang != NIL)
  798.                                         {
  799.                                             TextEditAppendLineInteraction(Window->Editor,Thang);
  800.                                             ReleasePtr(Thang);
  801.                                         }
  802.                                      else
  803.                                         {
  804.                                             MemoryErrorOccurred = True;
  805.                                         }
  806.                                 }
  807.                              else
  808.                                 {
  809.                                     long                    Scan;
  810.                                     long                    ElementSize;
  811.                                     long                    Limit;
  812.  
  813.                                     switch (ReturnType)
  814.                                         {
  815.                                             case eArrayOfBoolean:
  816.                                                 ElementSize = sizeof(char);
  817.                                                 break;
  818.                                             case eArrayOfInteger:
  819.                                                 ElementSize = sizeof(long);
  820.                                                 break;
  821.                                             case eArrayOfFixed:
  822.                                                 ElementSize = sizeof(largefixedsigned);
  823.                                                 break;
  824.                                             case eArrayOfFloat:
  825.                                                 ElementSize = sizeof(float);
  826.                                                 break;
  827.                                             case eArrayOfDouble:
  828.                                                 ElementSize = sizeof(double);
  829.                                                 break;
  830.                                             default:
  831.                                                 EXECUTE(PRERR(ForceAbort,
  832.                                                     "CalculatorWindowDoCalculation:  type filter failure"));
  833.                                                 break;
  834.                                         }
  835.                                     Limit = PtrSize((char*)Array) / ElementSize;
  836.                                     for (Scan = 0; (Scan < Limit) && !MemoryErrorOccurred
  837.                                         && !RelinquishCPUJudiciouslyCheckCancel(); Scan += 1)
  838.                                         {
  839.                                             char*                    LineNum;
  840.  
  841.                                             LineNum = IntegerToString(Scan);
  842.                                             if (LineNum != NIL)
  843.                                                 {
  844.                                                     char*                    Data;
  845.  
  846.                                                     switch (ReturnType)
  847.                                                         {
  848.                                                             case eArrayOfBoolean:
  849.                                                                 if (((char*)Array)[Scan])
  850.                                                                     {
  851.                                                                         Data = StringToBlockCopy("true");
  852.                                                                     }
  853.                                                                  else
  854.                                                                     {
  855.                                                                         Data = StringToBlockCopy("false");
  856.                                                                     }
  857.                                                                 break;
  858.                                                             case eArrayOfInteger:
  859.                                                                 Data = IntegerToString(((long*)Array)[Scan]);
  860.                                                                 break;
  861.                                                             case eArrayOfFixed:
  862.                                                                 Data = LongDoubleToString(largefixed2double(
  863.                                                                     ((largefixedsigned*)Array)[Scan]),11,1e-9,1e6);
  864.                                                                 break;
  865.                                                             case eArrayOfFloat:
  866.                                                                 Data = LongDoubleToString(((float*)
  867.                                                                     Array)[Scan],7,1e-4,1e6);
  868.                                                                 break;
  869.                                                             case eArrayOfDouble:
  870.                                                                 Data = LongDoubleToString(((double*)
  871.                                                                     Array)[Scan],15,1e-4,1e6);
  872.                                                                 break;
  873.                                                             default:
  874.                                                                 EXECUTE(PRERR(ForceAbort,
  875.                                                                     "CalculatorWindowDoCalculation:  type filter failure"));
  876.                                                                 break;
  877.                                                         }
  878.                                                     if (Data != NIL)
  879.                                                         {
  880.                                                             char*                LineNumCopy;
  881.  
  882.                                                             if (PtrSize(LineNum) > 16 - 1)
  883.                                                                 {
  884.                                                                     LineNumCopy = CopyPtr(LineNum);
  885.                                                                 }
  886.                                                              else
  887.                                                                 {
  888.                                                                     long                Index;
  889.  
  890.                                                                     LineNumCopy = AllocPtrCanFail(16,"LineNumCopy");
  891.                                                                     if (LineNumCopy != NIL)
  892.                                                                         {
  893.                                                                             for (Index = 0; Index < 16; Index += 1)
  894.                                                                                 {
  895.                                                                                     LineNumCopy[Index] = 32;
  896.                                                                                 }
  897.                                                                             CopyData(LineNum,LineNumCopy,PtrSize(LineNum));
  898.                                                                             LineNumCopy[PtrSize(LineNum)] = ':';
  899.                                                                         }
  900.                                                                 }
  901.                                                             if (LineNumCopy != NIL)
  902.                                                                 {
  903.                                                                     char*                    Total;
  904.  
  905.                                                                     Total = ConcatBlockCopy(LineNumCopy,Data);
  906.                                                                     if (Total != NIL)
  907.                                                                         {
  908.                                                                             TextEditAppendLineInteraction(Window->Editor,Total);
  909.                                                                             ReleasePtr(Total);
  910.                                                                         }
  911.                                                                      else
  912.                                                                         {
  913.                                                                             MemoryErrorOccurred = True;
  914.                                                                         }
  915.                                                                     ReleasePtr(LineNumCopy);
  916.                                                                 }
  917.                                                              else
  918.                                                                 {
  919.                                                                     MemoryErrorOccurred = True;
  920.                                                                 }
  921.                                                             ReleasePtr(Data);
  922.                                                         }
  923.                                                      else
  924.                                                         {
  925.                                                             MemoryErrorOccurred = True;
  926.                                                         }
  927.                                                     ReleasePtr(LineNum);
  928.                                                 }
  929.                                              else
  930.                                                 {
  931.                                                     MemoryErrorOccurred = True;
  932.                                                 }
  933.                                         }
  934.                                 }
  935.                         }
  936.                      else
  937.                         {
  938.                             MemoryErrorOccurred = True;
  939.                         }
  940.                     break;
  941.             }
  942.         /* add final terminating thing */
  943.         TextEditAppendLineInteraction(Window->Editor,NIL);
  944.         TextEditShowSelection(Window->Editor);
  945.         if (MemoryErrorOccurred)
  946.             {
  947.                 AlertHalt("There is not enough memory available to completely display the "
  948.                     "results of evaluating the function.",NIL);
  949.             }
  950.  
  951.         /* remember new last line */
  952.         Window->LastLine = GetTextEditNumLines(Window->Editor) - 1;
  953.  
  954.         /* dispose of stuff */
  955.         DisposeParamStack(ParamList);
  956.         DisposePcode(FuncCode);
  957.     }
  958.